#include "typedef.h"
#include "macros.h"
#include "board.h"
#include "hal_int.h"
#include "hal_timer2.h"
#include "Timer.h"

#define   TIMER_STATE_STOP               (0x01)
#define   TIMER_STATE_RUNNING            (0x02)
#define   TIMER_STATE_OVER               (0x03) 
#define   TIMER_STATE_NOT_USED           (0x04)



#define  TANS_TIME2TICK(x)    (((x))/TICKS_PER_SEC)


static  RTC_TIMER    RTC_Timer;
static  TIMER  Timers[TIMER_NUMBER];


void   Timer_Init(void);
INT8U  Timer_Apply(INT32U Time_ms , INT8U* err);
INT8U  StartTimer(INT8U TimeID);
INT8U  isTimeOver(INT8U TimeID);
void   StopTimer(INT8U TimeID);
void   DelTimer(INT8U TimeID);
TIMER* GetTimerHandle(INT8U TimeID);

static void  TimerIsr(void);


//----------------------------------------------------------------------------------
//  void  Timer_Init(void)
//
//  DESCRIPTION:
//    Initialize the Timers, fill the Timers with zero and initialize
//    with not used state.
//
//  ARGUMENTS:
//    None
//
//  RETURNS:
//    None
//----------------------------------------------------------------------------------
void  Timer_Init(void)
{
   INT8U i;
   for( i = 0 ; i < TIMER_NUMBER ; i++)
   {
        Timers[i].TimCount = 0;
        Timers[i].TimState = TIMER_STATE_NOT_USED;
   }
   
   RTC_Timer.Ticks = 0 ;
   RTC_Timer.Time_s = 0;
   
   halTimer2CompIntConnect(TimerIsr);
   halTimer2Init();   
}

//----------------------------------------------------------------------------------
//  INT8U Timer_Apply(INT32U Time_ms , INT8U* err)
//
//  DESCRIPTION:
//    Apply a user required Timer, the min time unit is 31.25ms, range (0 - 134217728ms).
//    The function return a ID for user, which can used to control the timer
//
//  ARGUMENTS:
//    Time_ms   -  the time required by user
//    err       -  the err return by the function 
//
//  RETURNS:
//    i        -   the TimerID
//----------------------------------------------------------------------------------
INT8U Timer_Apply(INT32U Time_ms , INT8U* err)
{
   INT8U  i;
   INT8U  McuState;
   
   *err = TIMER_NO_ERR;
   for( i = 0 ; i < TIMER_NUMBER ; i++)
   {
     if(Timers[i].TimState == TIMER_STATE_NOT_USED)
     {
        break;
     }
   }
   if(i == TIMER_NUMBER)
   {
     *err = TIMER_ERR_NO_MORE_TIMERS;
     return 0xff;
   }
   else
   {
     HAL_INT_LOCK(McuState);
       
     Timers[i].TimState = TIMER_STATE_STOP;
     Timers[i].TimLimit = TANS_TIME2TICK(Time_ms);
     
     HAL_INT_UNLOCK(McuState);
     return  i;
   }
}

//----------------------------------------------------------------------------------
//  INT8U  StartTimer(INT8U TimeID)
//
//  DESCRIPTION:
//    Start the Timer which the TimeID is reference
//
//  ARGUMENTS:
//    TimeID    -  the timer ID provide by user
//
//  RETURNS:
//    TIMER_NO_ERR    -   The Timer start success
//    TIMER_START_ERR -   The Timer start failed
//----------------------------------------------------------------------------------
INT8U  StartTimer(INT8U TimeID)
{
   INT8U  McuState;
   if(Timers[TimeID].TimState == TIMER_STATE_STOP)
   {
     HAL_INT_LOCK(McuState);
     
     Timers[TimeID].TimState = TIMER_STATE_RUNNING;
     
     HAL_INT_UNLOCK(McuState);
     return  TIMER_NO_ERR;
   }
   else
     return  TIMER_START_ERR;
}

//----------------------------------------------------------------------------------
//  void  TimerIsr(void)
//
//  DESCRIPTION:
//    The timer runs ISR,increase the count of any running timer and RTC timer.
//    If the timer's count is arrived the limit,the timer enter to TIMER_STATE_OVER,
//    the user can use function isTimeOver() to judge the timer state
//
//  ARGUMENTS:
//    TimeID    -  the timer ID provide by user
//
//  RETURNS:
//    TIMER_NO_ERR    -   The Timer start success
//    TIMER_START_ERR -   The Timer start failed
//----------------------------------------------------------------------------------
static void  TimerIsr(void)
{
  INT8U i; 
  for( i = 0 ; i < TIMER_NUMBER ; i++)
  {
      if(TIMER_STATE_RUNNING == Timers[i].TimState)
      {
         
         if(Timers[i].TimCount == Timers[i].TimLimit)
         {
           Timers[i].TimState = TIMER_STATE_OVER;
           Timers[i].TimCount = 0;
         }
         else
            Timers[i].TimCount++;
      }
  }
  RTC_Timer.Ticks++;
  if(TICKS_PER_SEC == RTC_Timer.Ticks)
  {
    RTC_Timer.Time_s++;
    RTC_Timer.Ticks = 0;
  }
}

//----------------------------------------------------------------------------------
//  INT8U  isTimeOver(INT8U TimeID)
//
//  DESCRIPTION:
//    Judge the Timer which the TimeID is reference,is arrived the user required
//
//  ARGUMENTS:
//    TimeID    -  the timer ID provide by user
//
//  RETURNS:
//    TRUE    -   The Timer arrived 
//    FALSE   -   The Timer is not arrived 
//----------------------------------------------------------------------------------
INT8U isTimeOver(INT8U TimeID)
{
   if(Timers[TimeID].TimState == TIMER_STATE_OVER)
   {
     return  TRUE;
   }
   else
     return  FALSE;
}

//----------------------------------------------------------------------------------
//  INT8U  StopTimer(INT8U TimeID)
//
//  DESCRIPTION:
//    Stop the Timer which the TimeID is reference
//
//  ARGUMENTS:
//    TimeID    -  the timer ID provide by user
//
//  RETURNS:
//    None
//----------------------------------------------------------------------------------
void  StopTimer(INT8U TimeID)
{
   INT8U  McuState;
   HAL_INT_LOCK(McuState);
   
   Timers[TimeID].TimCount = 0;
   Timers[TimeID].TimState = TIMER_STATE_STOP;
   
   HAL_INT_UNLOCK(McuState);
}

//----------------------------------------------------------------------------------
//  INT8U  DelTimer(INT8U TimeID)
//
//  DESCRIPTION:
//    Del the Timer which the TimeID is reference
//
//  ARGUMENTS:
//    TimeID    -  the timer ID provide by user
//
//  RETURNS:
//    None
//----------------------------------------------------------------------------------
void DelTimer(INT8U TimeID)
{
   INT8U  McuState;
   
   StopTimer(TimeID);
   
   HAL_INT_LOCK(McuState);
   Timers[TimeID].TimLimit = 0;
   Timers[TimeID].TimState = TIMER_STATE_NOT_USED;
   HAL_INT_UNLOCK(McuState);
}

//----------------------------------------------------------------------------------
//  TIMER*   GetTimerHandle(INT8U TimeID)
//
//  DESCRIPTION:
//    Get the Timer's pointer by TimeID 
//
//  ARGUMENTS:
//    TimeID    -  the timer ID provide by user
//
//  RETURNS:
//    Timer     -  the point to the timer
//----------------------------------------------------------------------------------
TIMER*   GetTimerHandle(INT8U TimeID)
{
  return  &Timers[TimeID];
}

//----------------------------------------------------------------------------------
//  INT32U GetRTCTime(void)
//
//  DESCRIPTION:
//    Get the RTC time of the system 
//
//  ARGUMENTS:
//    None    
//
//  RETURNS:
//    RTC_Timer.Time_s   -   The RTC counts of time base on second    
//----------------------------------------------------------------------------------
INT32U GetRTCTime(void)
{
   return RTC_Timer.Time_s;
}

//----------------------------------------------------------------------------------
//  void SetRTCTime(INT32U Time)
//
//  DESCRIPTION:
//    Set the RTC time of the system 
//
//  ARGUMENTS:
//    Time   -  The RTC counts of time base on second    
//
//  RETURNS:
//    None    
//----------------------------------------------------------------------------------
void SetRTCTime(INT32U Time)
{
  INT8U  McuState;
  HAL_INT_LOCK(McuState); 
  
  RTC_Timer.Time_s = Time;
  
  HAL_INT_UNLOCK(McuState);
}